// $codepro.audit.disable lineLength, com.instantiations.assist.eclipse.analysis.unusedReturnValue
/*
 * TLA.java
 * Jake Gibel 2012
 */

// $codepro.audit.disable avoidUtilityMethods, debuggingCode
package com.gmail.jakegibel.TLA;



import java.util.List;
import java.util.logging.Logger;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;



import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Snowball;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;



import org.bukkit.util.Vector;
import net.minecraft.server.EntityFireball;
import net.minecraft.server.EntityLiving;
import net.minecraft.server.EntitySmallFireball;
/**
 * @author Jake Gibel
 * @version %I%, %G%
 */
public final class TLA extends JavaPlugin{
    //private int[] earthBendableBlocks = {0};
    /**
     * LOG is the logger used to send information to the server
     */
    private static final Logger LOG = Logger.getLogger("Minecraft");

    /**
     * pm is the plugin manager that will allow the server to interface with plugins
     */
    private PluginManager pm;
    
    /**
     * What happens when the plugin is enabled on the server
     * @see org.bukkit.plugin.Plugin#onEnable()
     */
    @Override
    public void onEnable(){
        if(null != LOG){
            LOG.info("TLA v" + getDescription().getVersion() + " is now enabled...");
        }
        pm = this.getServer().getPluginManager();
        if(null != pm){
            pm.registerEvents(new TLAPlayerListener(this), this);
        }
    }
    
    /**
     * What happens when the plugin is disabled by the server
     * @see org.bukkit.plugin.Plugin#onDisable()
     */
    @Override
    public void onDisable(){
        if(null != LOG){
            LOG.info("TLA v" + getDescription().getVersion() + " is now disabled");
        }
    }

    /**
     * this method will shoot the fireball from the player 
     * in the direction that the player is looking
     * @param player Player that the fireball is shot from
     */
    public void shootFireball(Player player) {
        if(null !=  player){
            final Vector traject = player.getLocation().getDirection().multiply(5); //traject gives the direction that the player head is looking towards
            if(null != traject){
                final EntityLiving playerEntity = ((CraftPlayer) player).getHandle(); //playerEntity is the actual player used to generate the fireball
                final EntitySmallFireball fireBall = new EntitySmallFireball(
                                ((CraftWorld) player.getWorld()).getHandle(), playerEntity, 
                                traject.getX(), traject.getY(), traject.getZ()); //fireBall is the fireBall generated by player, and directions
                fireBall.locY = player.getLocation().getY() + (player.getEyeHeight() / 2.0) + 0.5;
                fireBall.locZ = player.getLocation().getZ() + (traject.getZ() / 10.0);
                fireBall.locX = player.getLocation().getX() + (traject.getX() / 10.0);
                ((CraftWorld) player.getWorld()).getHandle().addEntity(fireBall);
            }
        }
    }

    /**
     * This will shoot a snowball from the player
     * in the direction that the player is looking
     * @param player Player that the snowball will be shot from
     */
    public static void shootSnowBall(Player player){
        if(null != player){
    
        player.launchProjectile(Snowball.class);
        }
    }

    /**
     * Shoots a ghast ball which will create an explosion when it lands
     * The ball is shot from Player in the direction that they are looking
     *@param player Player that the ghast ball will be shot from
     */
    public void shootExplosion(Player player) {
        if(null != player){
            final Vector traject = player.getLocation().getDirection().multiply(5); //traject gives the direction that the player head is looking towards
            if(null != traject){
                final EntityLiving playerEntity = ((CraftPlayer) player).getHandle(); //playerEntity is the actual player used to generate the fireball
                final EntityFireball fireBall = new EntityFireball(
                        ((CraftWorld) player.getWorld()).getHandle(), playerEntity,
                        traject.getX(), traject.getY(), traject.getZ()); //fireBall is the fireBall generated by player, and directions
                fireBall.locY = player.getLocation().getY() + (player.getEyeHeight() / 2.0) + 0.5;
                fireBall.locZ = player.getLocation().getZ() + (traject.getZ() / 10.0);
                fireBall.locX = player.getLocation().getX() + (traject.getX() / 10.0);
                ((CraftWorld) player.getWorld()).getHandle().addEntity(fireBall);
            }
        }
    }

    /**
     * Toggles the block from ice to stationary water and vice versa
     * @param block the block to be switched to/from ice
     */
    public static void switchIce(Block block) {
        if(null != block){
            if(block.getType() == Material.ICE){
                block.setType(Material.STATIONARY_WATER);
            } else {
                block.setType(Material.ICE);
            }
        }
    }

    /**
     * Shoots an airblast which will knock back all entities within ten blocks.
     * The entities will be shot in a direction away from the player
     * @param player Player the center of the ten block radius
     *  from which the airblast will be shot from
     */
    public static void airBlast(Player player){
        if(null != player){
            final LivingEntity living = player; //living is the player in the world
            final List<Entity> entities = living.getNearbyEntities(10, 10, 10);
            for(Entity ent: entities){
                //System.out.println(ent.getEntityId());
                if(null != ent){
                    if(ent.getEntityId() >= 0){
                        int velX; //the X direction velocity
                        int velZ; //the Z direction velocity 
                        velX = ent.getLocation().getBlockX() - player.getLocation().getBlockX();
                        velZ = ent.getLocation().getBlockZ() - player.getLocation().getBlockZ();
                        velX /= 2;
                        velZ /= 2;
                        System.out.print(velX);
                        System.out.print(' ');
                        System.out.println(velZ);
                        ent.setVelocity(new Vector(velX, .5f, velZ));
        
                    }
                }
            }
        }
    }

    /**
     * This will push the earth away from the player in a 3x2x1 block. 
     * the direction is dependant on which block face you hit
     * @param player the player that is pushing the blocks
     * @param block Block the initial block clicked, or the top center of the 3x2x1 prism
     * @param blockFace BlockFace the direction of the 
     * block clicked, or which way to push the block
     */
    public static void pushEarth(Player player, Block block, BlockFace blockFace) {
        //System.out.println(blockFace);
        int bendingLevel = 2; //the depth of the block that will be pushed // $codepro.audit.disable unusedAssignment
        int typeBlockAbove; //the type of the block above it
        
        //System.out.println("Coords of block clicked: " + block.getX() + ", " + block.getY() + ", " + block.getZ());
        if(((null != player) && (null != block)) && (null != blockFace)){
            for(int i = -1; i <= 1 ; i++){
                for(int j = -bendingLevel; j <= 0; j++){
                    if(blockFace == BlockFace.UP){
                        typeBlockAbove = player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() + j + 1, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() + j, block.getZ()).setTypeId(typeBlockAbove);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() + j, block.getZ()).getTypeId());
                    } else if(blockFace == BlockFace.SOUTH){
                        typeBlockAbove = player.getWorld().getBlockAt(
                                block.getX() + j + 1, block.getY() + i, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() + j, block.getY() + i, block.getZ()).setTypeId(typeBlockAbove);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() + j, block.getY() + i, block.getZ()).getTypeId());
                    } else if(blockFace == BlockFace.WEST){
                        typeBlockAbove = player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() + j + 1).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() + j).setTypeId(typeBlockAbove);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() + j).getTypeId());
                    } else if(blockFace == BlockFace.EAST){
                        typeBlockAbove = player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() - j - 1).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() - j).setTypeId(typeBlockAbove);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() - j).getTypeId());
                    } else if(blockFace == BlockFace.NORTH){
                        typeBlockAbove = player.getWorld().getBlockAt(
                                block.getX() - j - 1, block.getY() + i, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() - j, block.getY() + i, block.getZ()).setTypeId(typeBlockAbove);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() - j, block.getY() + i, block.getZ()).getTypeId());
                    } else if(blockFace == BlockFace.DOWN){
                        typeBlockAbove = player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() - j - 1, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() - j, block.getZ()).setTypeId(typeBlockAbove);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() - j, block.getZ()).getTypeId());
                       
                    }
                }
            }
        }
    }

    /**
     * This will pull the earth towards the player in a 3x2x1 block. the direction is dependant on which block face you hit
     * @param player the player that is pushing the blocks
     * @param block Block the initial block clicked, or the top center of the 3x2x1 prism
     * @param blockFace BlockFace the direction of the block clicked, or which way to pull the block
     */
    public static void pullEarth(Player player, Block block, BlockFace blockFace) {
        //System.out.println(blockFace);
        int typeBlockBelow; //the type of the block below a certain block
        int bendingLevel = 2; //the depth of the block that will be pulled // $codepro.audit.disable unusedAssignment
        
        //System.out.println("Coords of block clicked: " + block.getX() + ", " + block.getY() + ", " + block.getZ());
        if(((null != player) && (null != block)) && (null != blockFace)){
            for(int i = -1; i <= 1 ; i++){
                for(int j = 1; j > -bendingLevel; j--){
                    if(blockFace == BlockFace.UP){
                        typeBlockBelow = player.getWorld().getBlockAt(
                                block.getX() + i, (block.getY() + j) - 1, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() + j, block.getZ()).setTypeId(typeBlockBelow);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() + j, block.getY() + i, block.getZ()).getTypeId());
                       
                    } else if(blockFace == BlockFace.SOUTH){
                        typeBlockBelow = player.getWorld().getBlockAt((
                                block.getX() + j) - 1, block.getY() + i, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() + j, block.getY() + i, block.getZ()).setTypeId(typeBlockBelow);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() + j, block.getY() + i, block.getZ()).getTypeId());
                    } else if(blockFace == BlockFace.WEST){
                        typeBlockBelow = player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, (block.getZ() + j) - 1).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() + j).setTypeId(typeBlockBelow);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() + j).getTypeId());
                    } else if(blockFace == BlockFace.EAST){
                        typeBlockBelow = player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, (block.getZ() - j) + 1).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() - j).setTypeId(typeBlockBelow);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX(), block.getY() + i, block.getZ() - j).getTypeId());
                    } else if(blockFace == BlockFace.NORTH){
                        typeBlockBelow = player.getWorld().getBlockAt((
                                block.getX() - j) + 1, block.getY() + i, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() - j, block.getY() + i, block.getZ()).setTypeId(typeBlockBelow);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() - j, block.getY() + i, block.getZ()).getTypeId());
                    } else if(blockFace == BlockFace.DOWN){
                        typeBlockBelow = player.getWorld().getBlockAt(
                                block.getX() + i, (block.getY() - j) + 1, block.getZ()).getTypeId();
                        player.getWorld().getBlockAt(
                                block.getX() + i, block.getY() - j, block.getZ()).setTypeId(typeBlockBelow);
                        System.out.println(player.getWorld().getBlockAt(
                                block.getX() + j, block.getY() + i, block.getZ()).getTypeId());
                       
                    }
                }
            }
        }
    }

    /**
     * Toggles flight on the player
     * @param player the player to have flight toggled
     */
    public static void toggleFlight(Player player) {
        if(null != player){
            if(player.getAllowFlight()){
                player.setAllowFlight(false);
                player.setFlying(false);
            } else {
                player.setAllowFlight(true);
                player.setFlying(true);
            }
        }
    }

}